Public Function PointInside(ByVal X As Single, ByVal Y As Single) As Boolean
Dim i As Integer
Dim theta1 As Double
Dim theta2 As Double
Dim dtheta As Double
Dim dx As Double
Dim dy As Double
Dim angles As Double
dx = Points(NumPts).trans(1) - X
dy = Points(NumPts).trans(2) - Y
theta1 = ATan2(CSng(dy), CSng(dx))
If theta1 < 0 Then theta1 = theta1 + 2 * PI
For i = 1 To NumPts
dx = Points(i).trans(1) - X
dy = Points(i).trans(2) - Y
theta2 = ATan2(CSng(dy), CSng(dx))
If theta2 < 0 Then theta2 = theta2 + 2 * PI
dtheta = theta2 - theta1
If dtheta > PI Then dtheta = dtheta - 2 * PI
If dtheta < -PI Then dtheta = dtheta + 2 * PI
angles = angles + dtheta
theta1 = theta2
Next i
PointInside = (Abs(angles) > 0.001)
End Function
' Return True if this polygon is completly above
' the plane containing target.
Public Function IsAbove(ByVal target As Face3d) As Boolean
Dim nx As Single
Dim ny As Single
Dim nz As Single
Dim px As Single
Dim py As Single
Dim pz As Single
Dim dx As Single
Dim dy As Single
Dim dz As Single
Dim cx As Single
Dim cy As Single
Dim cz As Single
Dim i As Integer
' Compute an upward pointing normal to the plane.
target.TransformedNormalVector nx, ny, nz
If nz < 0 Then
nx = -nx
ny = -ny
nz = -nz
End If
' Get a point on the plane.
target.GetTransformedPoint 1, px, py, pz
' See if the points in this polygon all lie
' above the plane containing target.
For i = 1 To NumPts
' Get the vector from plane to point.
dx = Points(i).trans(1) - px
dy = Points(i).trans(2) - py
dz = Points(i).trans(3) - pz
' If the dot product < 0, the point is
' below the plane.
If dx * nx + dy * ny + dz * nz < -0.01 Then
IsAbove = False
Exit Function
End If
Next i
IsAbove = True
End Function
' Return true if this polygon is completly below
' the plane containing target.
Public Function IsBelow(ByVal target As Face3d) As Boolean
Dim nx As Single
Dim ny As Single
Dim nz As Single
Dim px As Single
Dim py As Single
Dim pz As Single
Dim dx As Single
Dim dy As Single
Dim dz As Single
Dim cx As Single
Dim cy As Single
Dim cz As Single
Dim i As Integer
' Compute a downward pointing normal to the plane.
target.TransformedNormalVector nx, ny, nz
If nz > 0 Then
nx = -nx
ny = -ny
nz = -nz
End If
' Get a point on the plane.
target.GetTransformedPoint 1, px, py, pz
' See if the points in this polygon all lie
' below the plane containing target.
For i = 1 To NumPts
' Get the vector from plane to point.
dx = Points(i).trans(1) - px
dy = Points(i).trans(2) - py
dz = Points(i).trans(3) - pz
' If the dot product < 0, the point is
' below the plane.
If dx * nx + dy * ny + dz * nz < -0.01 Then
IsBelow = False
Exit Function
End If
Next i
IsBelow = True
End Function
' Return the transformed coordinates of a point
' on the polygon.
Public Sub GetTransformedPoint(ByVal Index As Long, ByRef X As Single, ByRef Y As Single, ByRef z As Single)
X = Points(Index).trans(1)
Y = Points(Index).trans(2)
z = Points(Index).trans(3)
End Sub
' Return the bounds of this polygon.
Public Sub GetExtent(ByRef Xmin As Single, ByRef xmax As Single, ByRef ymin As Single, ByRef ymax As Single, ByRef zmin As Single, ByRef zmax As Single)
Dim i As Integer
If NumPts < 1 Then Exit Sub
With Points(1)
Xmin = .trans(1)
xmax = Xmin
ymin = .trans(2)
ymax = ymin
zmin = .trans(3)
zmax = zmin
End With
For i = 2 To NumPts
With Points(i)
If Xmin > .trans(1) Then Xmin = .trans(1)
If xmax < .trans(1) Then xmax = .trans(1)
If ymin > .trans(2) Then ymin = .trans(2)
If ymax < .trans(2) Then ymax = .trans(2)
If zmin > .trans(3) Then zmin = .trans(3)
If zmax < .trans(3) Then zmax = .trans(3)
End With
Next i
End Sub
' Compute a normal vector for this polygon.
Public Sub NormalVector(ByRef nx As Single, ByRef ny As Single, ByRef nz As Single)
Dim Ax As Single
Dim Ay As Single
Dim Az As Single
Dim Bx As Single
Dim By As Single
Dim Bz As Single
Ax = Points(2).coord(1) - Points(1).coord(1)
Ay = Points(2).coord(2) - Points(1).coord(2)
Az = Points(2).coord(3) - Points(1).coord(3)
Bx = Points(3).coord(1) - Points(2).coord(1)
By = Points(3).coord(2) - Points(2).coord(2)
Bz = Points(3).coord(3) - Points(2).coord(3)
m3Cross nx, ny, nz, Ax, Ay, Az, Bx, By, Bz
End Sub
' Compute a transformed normal vector for this polygon.
Public Sub TransformedNormalVector(ByRef nx As Single, ByRef ny As Single, ByRef nz As Single)
Dim Ax As Single
Dim Ay As Single
Dim Az As Single
Dim Bx As Single
Dim By As Single
Dim Bz As Single
Ax = Points(2).trans(1) - Points(1).trans(1)
Ay = Points(2).trans(2) - Points(1).trans(2)
Az = Points(2).trans(3) - Points(1).trans(3)
Bx = Points(3).trans(1) - Points(2).trans(1)
By = Points(3).trans(2) - Points(2).trans(2)
Bz = Points(3).trans(3) - Points(2).trans(3)
m3Cross nx, ny, nz, Ax, Ay, Az, Bx, By, Bz
End Sub
' Add one or more points to the polygon.
Public Sub AddPoints(ParamArray coord() As Variant)
Dim num_pts As Integer
Dim i As Integer
Dim pt As Integer
num_pts = (UBound(coord) + 1) \ 3
ReDim Preserve Points(1 To NumPts + num_pts)
pt = 0
For i = 1 To num_pts
Points(NumPts + i).coord(1) = coord(pt)
Points(NumPts + i).coord(2) = coord(pt + 1)
Points(NumPts + i).coord(3) = coord(pt + 2)
Points(NumPts + i).coord(4) = 1#
pt = pt + 3
Next i
NumPts = NumPts + num_pts
End Sub
' Apply a transformation matrix which may not
' contain 0, 0, 0, 1 in the last column to the
' object.
Public Sub ApplyFull(M() As Single)
Dim i As Integer
' Do nothing if we are culled.
If IsCulled Then Exit Sub
For i = 1 To NumPts
m3ApplyFull Points(i).coord, M, Points(i).trans
Next i
End Sub
' Apply a transformation matrix to the object.
Public Sub Apply(M() As Single)
Dim i As Integer
' Do nothing if we are culled.
If IsCulled Then Exit Sub
For i = 1 To NumPts
m3Apply Points(i).coord, M, Points(i).trans
Next i
End Sub
' Draw the transformed points on a Form, Printer,
' or PictureBox.
Public Sub Draw(ByVal pic As PictureBox, Optional r As Variant)
Dim pts() As POINTAPI
Dim i As Integer
' Do nothing if we are culled.
If IsCulled Then Exit Sub
If NumPts < 3 Then Exit Sub
ReDim pts(1 To NumPts)
For i = 1 To NumPts
pts(i).X = Points(i).trans(1)
pts(i).Y = Points(i).trans(2)
Next i
Polygon pic.hdc, pts(1), NumPts
End Sub
' Cull if any points are behind the center of
' projection.
Public Sub ClipEye(ByVal r As Single)
Dim pt As Integer
' Do nothing if we are already culled.
If IsCulled Then Exit Sub
For pt = 1 To NumPts
If Points(pt).trans(3) >= r Then Exit For
Next pt
If pt <= NumPts Then IsCulled = True
End Sub
' Perform backface removal for the center
' of projection (X, Y, Z).
Public Sub Cull(ByVal X As Single, ByVal Y As Single, ByVal z As Single)
Dim Ax As Single
Dim Ay As Single
Dim Az As Single
Dim nx As Single
Dim ny As Single
Dim nz As Single
' Compute a normal to the face.
NormalVector nx, ny, nz
' Compute a vector from the center of
' projection to the face.
Ax = Points(1).coord(1) - X
Ay = Points(1).coord(2) - Y
Az = Points(1).coord(3) - z
' See if the vectors meet at an angle < 90.
IsCulled = (Ax * nx + Ay * ny + Az * nz > -0.0001)
End Sub
' Return the largest transformed Z value for this face.